"""
TTS模块错误处理
定义火山引擎TTS API的错误码和异常类
"""
import json
from enum import IntEnum
from typing import Optional, Dict, Any


class TTSErrorCode(IntEnum):
    """TTS错误码枚举"""
    
    # 成功
    SUCCESS = 20000000
    
    # 客户端错误 (45000000 - 45999999)
    CLIENT_ERROR = 45000000
    CLIENT_INVALID_REQUEST = 45000001  # 客户端请求参数错误
    CLIENT_AUTH_FAILED = 45000002      # 认证失败
    CLIENT_QUOTA_EXCEEDED = 45000292   # 配额超限
    CLIENT_RATE_LIMIT = 45000293       # 请求频率超限
    CLIENT_INVALID_VOICE = 45000294    # 无效音色
    CLIENT_TEXT_TOO_LONG = 45000295    # 文本过长
    CLIENT_INVALID_FORMAT = 45000296   # 无效音频格式
    
    # 服务端错误 (55000000 - 55999999)
    SERVER_ERROR = 55000000
    SERVER_SESSION_ERROR = 55000001    # 服务端session错误
    SERVER_INTERNAL_ERROR = 55000002   # 服务端内部错误
    SERVER_UNAVAILABLE = 55000003      # 服务不可用
    SERVER_TIMEOUT = 55000004          # 服务端超时
    
    @classmethod
    def get_error_message(cls, code: int) -> str:
        """获取错误码对应的中文描述"""
        error_messages = {
            cls.SUCCESS: "成功",
            cls.CLIENT_ERROR: "客户端通用错误",
            cls.CLIENT_INVALID_REQUEST: "客户端请求参数错误",
            cls.CLIENT_AUTH_FAILED: "认证失败，请检查APP_ID和ACCESS_TOKEN",
            cls.CLIENT_QUOTA_EXCEEDED: "配额超限，请检查TTS服务配额或升级套餐",
            cls.CLIENT_RATE_LIMIT: "请求频率超限，请降低请求频率",
            cls.CLIENT_INVALID_VOICE: "无效音色，请检查音色参数",
            cls.CLIENT_TEXT_TOO_LONG: "文本过长，请分段处理",
            cls.CLIENT_INVALID_FORMAT: "无效音频格式，请检查格式参数",
            cls.SERVER_ERROR: "服务端通用错误",
            cls.SERVER_SESSION_ERROR: "服务端会话错误，请重试",
            cls.SERVER_INTERNAL_ERROR: "服务端内部错误，请稍后重试",
            cls.SERVER_UNAVAILABLE: "服务不可用，请稍后重试",
            cls.SERVER_TIMEOUT: "服务端超时，请重试",
        }
        return error_messages.get(code, f"未知错误码: {code}")
    
    @classmethod
    def is_client_error(cls, code: int) -> bool:
        """判断是否为客户端错误"""
        return 45000000 <= code < 46000000
    
    @classmethod
    def is_server_error(cls, code: int) -> bool:
        """判断是否为服务端错误"""
        return 55000000 <= code < 56000000
    
    @classmethod
    def is_retryable(cls, code: int) -> bool:
        """判断错误是否可重试"""
        # 服务端错误通常可重试，客户端错误通常不可重试
        retryable_codes = {
            cls.SERVER_ERROR,
            cls.SERVER_SESSION_ERROR,
            cls.SERVER_INTERNAL_ERROR,
            cls.SERVER_UNAVAILABLE,
            cls.SERVER_TIMEOUT,
        }
        return code in retryable_codes


class TTSError(Exception):
    """TTS基础异常类"""
    
    def __init__(self, message: str, error_code: Optional[int] = None, details: Optional[Dict[str, Any]] = None):
        super().__init__(message)
        self.error_code = error_code
        self.details = details or {}
        self.error_message = TTSErrorCode.get_error_message(error_code) if error_code else message
    
    def __str__(self) -> str:
        if self.error_code:
            return f"[{self.error_code}] {self.error_message}: {super().__str__()}"
        return super().__str__()
    
    @property
    def is_retryable(self) -> bool:
        """判断异常是否可重试"""
        return TTSErrorCode.is_retryable(self.error_code) if self.error_code else False


class TTSConnectionError(TTSError):
    """TTS连接错误"""
    pass


class TTSAuthenticationError(TTSError):
    """TTS认证错误"""
    pass


class TTSQuotaExceededError(TTSError):
    """TTS配额超限错误"""
    pass


class TTSRateLimitError(TTSError):
    """TTS请求频率超限错误"""
    pass


class TTSServerError(TTSError):
    """TTS服务端错误"""
    pass


class TTSSessionError(TTSError):
    """TTS会话错误"""
    pass


def parse_error_response(payload: bytes) -> Dict[str, Any]:
    """解析错误响应"""
    try:
        if payload:
            error_data = json.loads(payload.decode('utf-8'))
            return error_data
    except (json.JSONDecodeError, UnicodeDecodeError):
        pass
    return {}


def create_tts_exception(error_code: int, payload: bytes = b"") -> TTSError:
    """根据错误码创建对应的异常"""
    error_data = parse_error_response(payload)
    error_message = error_data.get('error', '')
    
    # 根据错误码创建特定异常
    if error_code == TTSErrorCode.CLIENT_AUTH_FAILED:
        return TTSAuthenticationError(
            error_message or "认证失败",
            error_code=error_code,
            details=error_data
        )
    elif error_code == TTSErrorCode.CLIENT_QUOTA_EXCEEDED:
        return TTSQuotaExceededError(
            error_message or "配额超限",
            error_code=error_code,
            details=error_data
        )
    elif error_code == TTSErrorCode.CLIENT_RATE_LIMIT:
        return TTSRateLimitError(
            error_message or "请求频率超限",
            error_code=error_code,
            details=error_data
        )
    elif TTSErrorCode.is_server_error(error_code):
        if error_code == TTSErrorCode.SERVER_SESSION_ERROR:
            return TTSSessionError(
                error_message or "会话错误",
                error_code=error_code,
                details=error_data
            )
        else:
            return TTSServerError(
                error_message or "服务端错误",
                error_code=error_code,
                details=error_data
            )
    else:
        return TTSError(
            error_message or "未知错误",
            error_code=error_code,
            details=error_data
        )


def get_quota_solution(error_code: int) -> str:
    """获取配额问题的解决方案"""
    if error_code == TTSErrorCode.CLIENT_QUOTA_EXCEEDED:
        return """
配额超限解决方案：
1. 登录火山引擎控制台查看TTS服务配额使用情况
2. 如果是免费套餐，考虑升级到付费套餐
3. 如果是按月配额，等待下个计费周期重置
4. 优化使用：减少测试频率，合并文本请求
5. 联系火山引擎技术支持申请临时配额
"""
    elif error_code == TTSErrorCode.CLIENT_RATE_LIMIT:
        return """
请求频率超限解决方案：
1. 降低请求频率，增加请求间隔
2. 使用批量请求减少API调用次数
3. 实现请求队列和限流机制
4. 考虑升级到更高QPS的套餐
"""
    return "请查看错误码文档获取详细解决方案"
